home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Support Library
/
RoseWare - Network Support Library.iso
/
apidev
/
nodlst.arc
/
NODELIST.C
< prev
next >
Wrap
Text File
|
1989-12-15
|
16KB
|
475 lines
/* */
/* NodeList - Display the configuration of all nodes on the LAN*/
/* */
/* by Charles Rose */
/* */
#include <stdio.h>
#include <dos.h>
#include "ipx.h"
#define IPX_QUERY_SOCKET 0x5604
#define MAX_RETRIES 5
#define ADDED 0x55
#define BRIDGE_DRIVER 1
#define SHELL_DRIVER 2
#define FIRST_SOCKET 0x8080
#define SECOND_SOCKET 0x8181
/* Local Prototypes */
void PrintDriverInfo( BYTE DriverType, WORD SessionSocket,
BYTE ShellComponentPosition, IPXAddress *Address );
void printAddress(BYTE byte[], int count);
void SetupECB( ECB *ECBptr, WORD *FragAddress, WORD Size );
void QueryDriver( WORD connectionID );
int InBridgeList( BYTE Node[6] );
void IPXGetProcAddress(void (*proc)(),WORD *addressField);
void IPXGetDataAddress(WORD *data,WORD *addressField);
IPXConfigRequest HoldRequest; /* Request for Configuration Packets */
IPXConfigReply HoldReply[MAX_NODES];
ECB SendECB;
ECB RcvECB[MAX_NODES];
SPXHeader EstSPXReq; /* Establish connection w/ target */
ECB EstECBReq;
SPXInfoRequest InfoRequest; /* Make request of Shell/Bridge for Config */
ECB InfoRequestECB;
SPXDriverReply InfoReply[10]; /* Receive response from Shell/Bridge */
ECB InfoReplyECB[10];
BYTE targetNetwork[4] = { 0, 0, 0, 0 };
BYTE targetNode[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
WORD targetSocket, socket;
BYTE BridgeExclude[MAX_NODES][6];
int ExcludeCount = 0;
WORD ticks;
void main()
{
int retcode, i, z, retries, isbridge;
IPXConfigReply *reply;
BYTE ShellComponentPosition;
WORD SessionSocket, querySocket = IPX_QUERY_SOCKET;
/* Print opening banner */
printf("NODELIST - Lists all nodes and their configurations.\n");
printf("Code and Article published in January 1990 NetWare Technical Journal\n");
printf("Copyright (c) 1989, McGraw-Hill, Inc.\n");
printf("Written by Charles Rose\n\n");
/* Make sure IPX is active and ok */
if ( !IPXInitialize() )
{
printf("IPX must be loaded for this program to run.\n");
exit(1);
}
/* Begin by opening a socket to send from */
socket = FIRST_SOCKET;
retcode = IPXOpenSocket( (BYTE*) &socket, TEMPORARY );
if ( retcode )
{
printf("Error opening socket %X. Error = %X.\n",
socket, retcode );
exit(1);
}
/* Setup array of listening ECBs */
for ( i = 0; i < MAX_NODES; i++ )
{
SetupECB( &RcvECB[i], &HoldReply[i], sizeof( IPXConfigReply ) );
IPXListenForPacket( &RcvECB[i] );
}
/* Send IPX Configuration Request */
SetupECB( &SendECB, &HoldRequest, sizeof( IPXConfigRequest ) );
HoldRequest.IPX.PacketType = 0;
HoldRequest.ExclusionCount = 0;
/* Setup for broadcast mode: Place 0's in Network Address and*/
/* 0xFF's in Node Address */
movmem( targetNode, SendECB.ImmediateAddress, 6);
movmem( targetNetwork, HoldRequest.IPX.Destination.Network, 4);
movmem( targetNode, HoldRequest.IPX.Destination.Node, 6);
/* Set to broadcast on the query Socket (456h) */
movmem( &querySocket, HoldRequest.IPX.Destination.Socket, 2);
IPXSendPacket( &SendECB );
while ( SendECB.InUseFlag )
IPXRelinquishControl();
if ( SendECB.CompletionCode )
{
printf( " Bad IPXSend, return = %x ", SendECB.CompletionCode );
exit(1);
}
/* Wait a second between each retry (give it a chance to respond) */
ticks = IPXGetIntervalMarker();
printf("Broadcasting Configuration Request...\n");
while ( ( IPXGetIntervalMarker() - ticks ) < 18 )
;
/* Check list of ECBs and re-send MAX_RETRIES times to be sure*/
/* all stations have responded */
retries = 0;
while ( retries < MAX_RETRIES )
{
for ( i = 0; i < MAX_NODES; i++ )
{
/* If this Receive ECB has received a good packet and*/
/* we haven't already added it to our exclude lists,*/
if ( !RcvECB[i].InUseFlag && !RcvECB[i].CompletionCode &&
RcvECB[i].CompletionCode != ADDED )
{
/* Mark it as added */
RcvECB[i].CompletionCode = ADDED;
/* Add it to the Exclusion Table if it's not a bridge */
/* Clear bridge flag */
isbridge = 0;
/* Check component list to see if there's a BRIDGE_DRIVER
present */
for ( z = 0; z < HoldReply[i].ComponentCount; z++ )
if ( HoldReply[i].ComponentType[z] == BRIDGE_DRIVER
)
isbridge++;
/* If no BRIDGE_DRIVER was found, add to the exclusion table
*/
/* and update the number of exclusions
*/
if ( !isbridge )
movmem( HoldReply[i].IPX.Source.Node,
HoldRequest.ExclusionAddress[HoldRequest.ExclusionCount++],
6 );
}
}
/* Re-send the configuration request */
IPXSendPacket( &SendECB );
while ( SendECB.InUseFlag != OKAY )
IPXRelinquishControl();
if ( SendECB.CompletionCode != OKAY )
{
printf( " Bad IPX Send, status = %x ", SendECB.CompletionCode);
exit(1);
}
/* Wait a second between each retry (give it a chance to respond) */
ticks = IPXGetIntervalMarker();
printf("Broadcasting Configuration Request...\n");
while ( ( IPXGetIntervalMarker() - ticks ) < 18 )
;
retries++;
}
/* Now iterate through list, contacting each node and producing*/
/* a report of each bridge and shell driver and their configuration */
/* First, show bridges */
printf( "=------------------------------------------------=\n");
printf( "=------------------------------------------------=\n");
printf( " File Servers/Bridges\n");
for ( i = 0; i < MAX_NODES; i++ )
{
/* If this ECB has not received anything, or if it received a*/
/* bad packet, move on to the next */
if ( RcvECB[i].CompletionCode != ADDED )
continue;
reply = (IPXConfigReply*) RcvECB[i].FragmentDescriptor.Address[0];
SessionSocket = reply->SPXDiagnosticSocket;
for ( z = 0; z < reply->ComponentCount ; z++ )
{
/* Ignore the shell drivers this go around */
if ( reply->ComponentType[z] == SHELL_DRIVER )
continue;
if ( reply->ComponentType[z] == BRIDGE_DRIVER )
{
/* We know this node is a bridge, let's make*/
/* sure we haven't contacted it before */
if ( !InBridgeList( HoldReply[i].IPX.Source.Node ) )
{
/* Add to Bridge List */
movmem( HoldReply[i].IPX.Source.Node,
BridgeExclude[ExcludeCount++], 6 );
/* print banner */
printf(
"=------------------------------------------------=\n");
printf( "Report for Node Address: ");
printAddress( HoldReply[i].IPX.Source.Node, 6 );
printf( "\n" );
/* Print info on our Bridge */
PrintDriverInfo( BRIDGE_DRIVER, SessionSocket, z,
&HoldReply[i].IPX.Source );
}
}
}
}
/* Now show workstations/shells */
printf( "=------------------------------------------------=\n");
printf( " Workstations\n");
for ( i = 0; i < MAX_NODES; i++ )
{
/* If this ECB has not received anything, or if it received a*/
/* bad packet, move on to the next */
if ( RcvECB[i].CompletionCode != ADDED )
continue;
reply = (IPXConfigReply*) RcvECB[i].FragmentDescriptor.Address[0];
SessionSocket = reply->SPXDiagnosticSocket;
for ( z = 0; z < reply->ComponentCount ; z++ )
{
/* Show the shell drivers this go around */
if ( reply->ComponentType[z] == SHELL_DRIVER )
{
/* print banner */
printf(
"=------------------------------------------------=\n");
printf( "Report for Node Address: ");
printAddress( HoldReply[i].IPX.Source.Node, 6 );
printf( "\n" );
PrintDriverInfo( SHELL_DRIVER, SessionSocket, z,
&HoldReply[i].IPX.Source );
}
/* Skip the bridges this time */
if ( reply->ComponentType[z] == BRIDGE_DRIVER )
continue;
}
}
printf( "=------------------------------------------------=\n");
printf( "=------------------------------------------------=\n");
IPXCloseSocket( socket );
}
void PrintDriverInfo( BYTE DriverType, WORD SessionSocket, BYTE ShellComponentPosition,
IPXAddress *Address )
{
int retcode, i, driver;
WORD connectionID;
/* This section, given a Session Socket, Component Position*/
/* and an IPXAddress structure, */
/* the routine should print the LAN Card type and configuration*/
/* info from the shells */
/* Close old socket, open a new one */
IPXCloseSocket( socket );
socket = SECOND_SOCKET;
retcode = IPXOpenSocket( (BYTE*) &socket, TEMPORARY );
if ( retcode )
{
printf("Error opening socket.\n");
exit(1);
}
/* Now, setup SPX connection. First, post listens*/
/* You need a few here; tried w/ one and didn't work always*/
for ( i = 0; i < 10; i++ )
{
SetupECB( &InfoReplyECB[i], &InfoReply[i], sizeof( SPXDriverReply ) );
SPXListenForSequencedPacket( &InfoReplyECB[i] );
}
/* Setup for Send SPX Connection Request */
/* Initialize the ECB */
SetupECB( &EstECBReq, &EstSPXReq, sizeof( SPXHeader ) );
EstSPXReq.PacketType = 5; /* SPX Packet */
/* Set Establish destination equal to config destination */
movmem( Address, &EstSPXReq.Destination, 10 );
/* Now set socket to that obtained from Configuration Request */
movmem( &SessionSocket, EstSPXReq.Destination.Socket, 2);
/* Make the connection (set retry to default (0) and set watchdog (1) */
retcode = SPXEstablishConnection( 0, 1, &connectionID, &EstECBReq );
if ( retcode )
{
printf("Can't Establish Connection, ret = %X\n", retcode );
exit(1);
}
while ( EstECBReq.InUseFlag && !(kbhit()) );
if ( EstECBReq.CompletionCode )
{
printf("Can't Establish Connection, Completion Code = %X\n",
EstECBReq.CompletionCode );
exit(1);
}
/* Connection has been established, now query shell */
SetupECB( &InfoRequestECB, &InfoRequest, sizeof( SPXInfoRequest ) );
InfoRequest.SPX.PacketType = 5; /* SPX Packet */
InfoRequest.ComponentPosition = ShellComponentPosition;
if ( DriverType == SHELL_DRIVER )
{
InfoRequest.RequestNumber = 0; /* Get Shell Driver Configuration */
QueryDriver( connectionID );
}
else
if ( DriverType == BRIDGE_DRIVER )
{
InfoRequest.RequestNumber = 1; /* Get Bridge Driver Configuration */
for ( driver = 0; driver < 4; driver++ )
{
InfoRequest.BridgeDriver = driver;
printf("LAN %c:\n", 'A' + driver );
QueryDriver( connectionID );
}
}
SPXTerminateConnection( connectionID, &EstECBReq );
while ( EstECBReq.InUseFlag && !kbhit() )
;
}
void QueryDriver( WORD connectionID )
{
int response, i;
/* Send the Shell Driver query */
SPXSendSequencedPacket( connectionID, &InfoRequestECB );
/* Now Check for a response, wait until there is one */
/* Scan InfoReply's for !InUseFlag, key can be hit to abort */
response = 0;
while ( !response && !kbhit() )
{
for ( i=0; i < 10; i++ )
{
if ( !InfoReplyECB[i].InUseFlag )
response = i+1;
}
}
if ( kbhit() )
{
getch();
printf("Key was hit while waiting for shell to respond");
exit(1);
}
/* If there is a bad response (such as when there are no more LAN*/
/* boards), then return */
if ( InfoReply[response-1].CompletionCode )
return;
/* Print configuration information */
printf("LAN Type is :\n");
printf("%s\n", InfoReply[response-1].LANDescription );
printf("\nLAN Setup is :\n");
printf("%s\n", InfoReply[response-1].TextDescription );
/* Finally, terminate the connection with this node */
SPXListenForSequencedPacket( &InfoReplyECB[response-1] );
}
void printAddress(BYTE byte[], int count)
{
int i;
for (i=0; i<count; i++)
printf("%02X", byte[i]);
}
void SetupECB( ECB *ECBptr, WORD *FragAddress, WORD Size )
{
/* Initialize the fields necessary for all of our ECB's */
ECBptr->ESRAddress = NULL;
ECBptr->InUseFlag = 0;
ECBptr->ECBSocket = socket;
ECBptr->FragmentCount = 1;
IPXGetDataAddress( (WORD *)FragAddress,
(WORD *)&ECBptr->FragmentDescriptor.Address );
ECBptr->FragmentDescriptor.Size = Size;
}
int InBridgeList( BYTE Node[6] )
{
int i, z, same;
for ( i = 0; i < ExcludeCount; i++ )
{
same = 1;
for ( z = 0; z < 6; z++ )
if ( Node[z] != BridgeExclude[i][z] )
{
same = 0;
break;
}
if ( same )
return (1);
}
return (0);
}
void IPXGetProcAddress(proc,addressField)
void (*proc)();
WORD addressField[2];
{
struct SREGS segregs;
segread(&segregs);
segregs.es = segregs.ds;
addressField[0] = (WORD) proc;
addressField[1] = (WORD) segregs.cs;
}
void IPXGetDataAddress(data,addressField)
WORD *data;
WORD addressField[2];
{
struct SREGS segregs;
segread(&segregs);
segregs.es = segregs.ds;
addressField[0] = (WORD) data;
addressField[1] = (WORD) segregs.ds;
}